# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.676.14.46 -> 1.676.14.47 # drivers/scsi/scsi_dma.c 1.2 -> 1.3 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/09/27 bjorn_helgaas@hp.com 1.676.14.47 # scsi_dma: Support for 64K pages. # -------------------------------------------- # diff -Nru a/drivers/scsi/scsi_dma.c b/drivers/scsi/scsi_dma.c --- a/drivers/scsi/scsi_dma.c Wed Oct 8 09:07:41 2003 +++ b/drivers/scsi/scsi_dma.c Wed Oct 8 09:07:41 2003 @@ -30,8 +30,69 @@ typedef unsigned char FreeSectorBitmap; #elif SECTORS_PER_PAGE <= 32 typedef unsigned int FreeSectorBitmap; -#else -#error You lose. +#elif SECTORS_PER_PAGE <= 64 +typedef u64 FreeSectorBitmap; +#elif SECTORS_PER_PAGE <= 128 + +typedef struct { + u64 hi, lo; +} FreeSectorBitmap; + +/* No side effects on MAP-macro-arguments, please... */ + +#define MAP_MAKE_MASK(m, nbits) \ +do { \ + if ((nbits) >= 64) { \ + (m).hi = ((u64) 1 << ((nbits) - 64)) - 1; \ + (m).lo = ~(u64) 0; \ + } else { \ + (m).hi = 0; \ + (m).lo = ((u64) 1 << (nbits)) - 1; \ + } \ +} while (0) + +#define MAP_SHIFT_LEFT(m, count) \ +do { \ + if ((count) >= 64) { \ + (m).hi = (m).lo << ((count) - 64); \ + (m).lo = 0; \ + } else { \ + (m).hi = ((m).hi << (count)) | ((m).lo >> (64 - (count))); \ + (m).lo <<= count; \ + } \ +} while (0) + +#define MAP_AND(r, left, right) \ +do { \ + (r).hi = (left).hi & (right).hi; \ + (r).lo = (left).lo & (right).lo; \ +} while (0) + +#define MAP_SET(r, mask) \ +do { \ + (r).hi |= (mask).hi; \ + (r).lo |= (mask).lo; \ +} while (0) + +#define MAP_CLEAR(r, mask) \ +do { \ + (r).hi &= ~(mask).hi; \ + (r).lo &= ~(mask).lo; \ +} while (0) + +#define MAP_EQUAL(left, right) (((left.hi ^ right.hi) | (left.lo ^ right.lo)) == 0) +#define MAP_EMPTY(m) ((m.lo | m.hi) == 0) + +#endif + +#ifndef MAP_MAKE_MASK +# define MAP_MAKE_MASK(m,nbits) ((m) = (((u64) 1 << (nbits)) - 1)) +# define MAP_SHIFT_LEFT(m,nbits) ((m) <<= (nbits)) +# define MAP_AND(res,l,r) ((res) = (l) & (r)) +# define MAP_EQUAL(l,r) ((l) == (r)) +# define MAP_EMPTY(m) ((m) == 0) +# define MAP_CLEAR(m, bits) ((m) &= ~(bits)) +# define MAP_SET(m, bits) ((m) |= (bits)) #endif /* @@ -71,7 +132,8 @@ */ void *scsi_malloc(unsigned int len) { - unsigned int nbits, mask; + FreeSectorBitmap mask, busy_sectors, result; + unsigned int nbits; unsigned long flags; int i, j; @@ -79,23 +141,29 @@ return NULL; nbits = len >> 9; - mask = (1 << nbits) - 1; spin_lock_irqsave(&allocator_request_lock, flags); - for (i = 0; i < dma_sectors / SECTORS_PER_PAGE; i++) + for (i = 0; i < dma_sectors / SECTORS_PER_PAGE; i++) { + MAP_MAKE_MASK(mask, nbits); + busy_sectors = dma_malloc_freelist[i]; for (j = 0; j <= SECTORS_PER_PAGE - nbits; j++) { - if ((dma_malloc_freelist[i] & (mask << j)) == 0) { - dma_malloc_freelist[i] |= (mask << j); + MAP_AND(result, busy_sectors, mask); + if (MAP_EMPTY(result)) { + MAP_SET(dma_malloc_freelist[i], mask); scsi_dma_free_sectors -= nbits; #ifdef DEBUG - SCSI_LOG_MLQUEUE(3, printk("SMalloc: %d %p [From:%p]\n", len, dma_malloc_pages[i] + (j << 9))); - printk("SMalloc: %d %p [From:%p]\n", len, dma_malloc_pages[i] + (j << 9)); + SCSI_LOG_MLQUEUE(3, printk("SMalloc: %d %p\n", + len, dma_malloc_pages[i] + (j << 9))); + printk("SMalloc: %d %p\n", + len, dma_malloc_pages[i] + (j << 9)); #endif spin_unlock_irqrestore(&allocator_request_lock, flags); return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9)); } + MAP_SHIFT_LEFT(mask, 1); } + } spin_unlock_irqrestore(&allocator_request_lock, flags); return NULL; /* Nope. No more */ } @@ -121,7 +189,8 @@ */ int scsi_free(void *obj, unsigned int len) { - unsigned int page, sector, nbits, mask; + FreeSectorBitmap mask, result; + unsigned int page, sector, nbits; unsigned long flags; #ifdef DEBUG @@ -145,13 +214,14 @@ sector = (((unsigned long) obj) - page_addr) >> 9; nbits = len >> 9; - mask = (1 << nbits) - 1; + MAP_MAKE_MASK(mask, nbits); if (sector + nbits > SECTORS_PER_PAGE) panic("scsi_free:Bad memory alignment"); - if ((dma_malloc_freelist[page] & - (mask << sector)) != (mask << sector)) { + MAP_SHIFT_LEFT(mask, sector); + MAP_AND(result, mask, dma_malloc_freelist[page]); + if (!MAP_EQUAL(result, mask)) { #ifdef DEBUG printk("scsi_free(obj=%p, len=%d) called from %08lx\n", obj, len, ret); @@ -159,7 +229,7 @@ panic("scsi_free:Trying to free unused memory"); } scsi_dma_free_sectors += nbits; - dma_malloc_freelist[page] &= ~(mask << sector); + MAP_CLEAR(dma_malloc_freelist[page], mask); spin_unlock_irqrestore(&allocator_request_lock, flags); return 0; }